const db = require('./db');
const co = require('co');

function coWrap(fn) {
    return function(...args) {
        return co(fn.apply(null, args));
    }
}

exports.fetch = coWrap(function* fetch(args = {}) {
    let {limit = 10, updatedAt, maxUpdatedAt}  = args;
    limit = Math.abs(~~limit) || 200;
    updatedAt = ~~updatedAt;
    if (limit > 500) {
        limit = 500;
    }
    let sql, rows;
    if (maxUpdatedAt && updatedAt) {
        sql = 'select * from seed where updated_at >= from_unixtime(?, "%Y-%m-%d %H:%i:%s") and updated_at < from_unixtime(?, "%Y-%m-%d %H:%i:%s") order by updated_at asc';
        rows = yield db.query(sql, [updatedAt, maxUpdatedAt]);
    } else if (updatedAt) {
        sql = 'select * from seed where updated_at >= from_unixtime(?, "%Y-%m-%d %H:%i:%s") order by updated_at asc limit ?';
        rows = yield db.query(sql, [updatedAt, limit]);
    } else {
        sql = 'select * from seed order by updated_at asc limit ?';
        rows = yield db.query(sql, [limit]);
    }
    if (!rows.length) {
        return rows;
    }
    let refIds = [];
    rows.forEach(row => {
        if (row.is_sync == 0) {
            refIds.push(row.infohash);
        }
    });

    let fileRows;
    if (refIds.length) {
        sql = 'select * from seed_file where infohash in (?)';
        fileRows = yield db.query(sql, [refIds]);
    } else {
        fileRows = [];
    }

    let files = {};
    fileRows.forEach(row => {
        if (!files[row.infohash]) {
            files[row.infohash] = [];
        }
        files[row.infohash].push(row);
    });
    rows.forEach(row => {
        if (row.is_sync == 0) {
            if (files[row.infohash])  {
                row.files = files[row.infohash];
            } else {
                row.files = [];
            }
        }
    });
    return rows;
});

exports.notify = coWrap(function* notify(infohashs) {
    if (!infohashs || !infohashs.length) {
        return false;
    }
    yield db.query("update seed set is_sync = 1, updated_at=updated_at where infohash in (?)", [infohashs]);
    return true;
});
